---
keywords:
- functions
- state
- structures
- storage
- named fields
description: The smart contracts can trigger events that the user can subscribe to and that convey changes to its state.
image: /img/logo/WASP_logo_dark.png
---

import Tabs from "@theme/Tabs"
import TabItem from "@theme/TabItem"

# Triggering Events

Smart contracts do not live in a vacuum. Even though they run in a very limited
sandbox, from a larger perspective there will have to be a way for users to interact
with them. Since smart contracts are essentially event-driven, and requests run
asynchronously from the user's perspective, there is a need for triggering events by
the smart contracts themselves. Of course, it would be possible for users to
periodically call a view function to retrieve the latest state of the smart contract,
but this burdens the nodes unnecessarily. A better way is to have the smart contracts
trigger events that the user can subscribe to and that convey changes to its state.

To support events the ISCP sandbox provides a very rudimentary interface. The function
call context exposes this interface through its `event()` function, which is passed a
completely arbitrary text string. It is up to the smart contract creator to format
this text string and it's up to the user to interpret this text string correctly. This
is error-prone, inconsistent, and means that a lot of code needs to be written both on
the smart contract side that generates these events, and on the client side that handles
these events. And with any change to the formatting of these events both ends need to be
modified to stay in sync.

This is why the [schema tool](usage.mdx) allows you to define your own structured events.
The schema tool will generate a structure that will become part of all func call contexts.
Events can only be triggered from within a func. They will become part of the state of the
smart contract because every event is logged in the core `eventlog` contract.
Therefore, they cannot be triggered from a view.

For each event defined in the `events` section of the schema definition file, this
events structure will contain a member function that takes the defined types of parameters
and will automatically encode the event as a consistently formatted string and pass it
to the ISCP context's `event()` function. The string consists of the name of the event,
a timestamp, and string representations of each field, all separated by vertical bars.

Here is the `events` section that can be found in the demo `fairroulette` smart contract:

<Tabs defaultValue="yaml"
      values={[
          {label: 'schema.yaml', value: 'yaml'},
          {label: 'schema.json', value: 'json'},
      ]}>

<TabItem value="json">

```json
"events": {
    "bet": {
        "address": "Address // address of better",
        "amount": "Int64 // amount of iotas to bet",
        "number": "Int64 // number to bet on",
    },
    "payout": {
        "address": "Address // address of winner",
        "amount": "Int64 // amount of iotas won",
    },
    "round": {
        "number": "Int64 // current betting round number"
    },
    "start": {
    },
    "stop": {
    },
    "winner": {
        "number": "Int64 // the winning number"
    }
}
```

</TabItem>

<TabItem value="yaml">

```yaml
events:
  bet:
    address: Address // address of better
    amount: Int64 // amount of iotas to bet
    number: Int64 // number to bet on
  payout:
    address: Address // address of winner
    amount: Int64 // amount of iotas won
  round:
    number: Int64 // current betting round number
  start:
  stop:
  winner:
    number: Int64 // the winning number
```

</TabItem>
</Tabs>

The schema tool will generate `events.xx` which contains the following code for the
FairRouletteEvents struct:

<Tabs defaultValue="go"
      groupId="language"
      values={[
          {label: 'Go', value: 'go'},
          {label: 'Rust', value: 'rust'},
          {label: 'TypeScript', value: 'ts'},
      ]}>

<TabItem value="go">

```go
package fairroulette

import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib"

type FairRouletteEvents struct{}

func (e FairRouletteEvents) Bet(address wasmlib.ScAddress, amount int64, number int64) {
    wasmlib.NewEventEncoder("fairroulette.bet").
    Address(address).
    Int64(amount).
    Int64(number).
    Emit()
}

func (e FairRouletteEvents) Payout(address wasmlib.ScAddress, amount int64) {
    wasmlib.NewEventEncoder("fairroulette.payout").
    Address(address).
    Int64(amount).
    Emit()
}

func (e FairRouletteEvents) Round(number int64) {
    wasmlib.NewEventEncoder("fairroulette.round").
    Int64(number).
    Emit()
}

func (e FairRouletteEvents) Start() {
    wasmlib.NewEventEncoder("fairroulette.start").
    Emit()
}

func (e FairRouletteEvents) Stop() {
    wasmlib.NewEventEncoder("fairroulette.stop").
    Emit()
}

func (e FairRouletteEvents) Winner(number int64) {
    wasmlib.NewEventEncoder("fairroulette.winner").
    Int64(number).
    Emit()
}
```

</TabItem>
<TabItem value="rust">

```rust
use wasmlib::*;

pub struct FairRouletteEvents {
}

impl FairRouletteEvents {
    pub fn bet(&self, address: &ScAddress, amount: i64, number: i64) {
        let mut encoder = EventEncoder::new("fairroulette.bet");
        encoder.address(&address);
        encoder.int64(amount);
        encoder.int64(number);
        encoder.emit();
    }

    pub fn payout(&self, address: &ScAddress, amount: i64) {
        let mut encoder = EventEncoder::new("fairroulette.payout");
        encoder.address(&address);
        encoder.int64(amount);
        encoder.emit();
    }

    pub fn round(&self, number: i64) {
        let mut encoder = EventEncoder::new("fairroulette.round");
        encoder.int64(number);
        encoder.emit();
    }

    pub fn start(&self) {
        EventEncoder::new("fairroulette.start").emit();
    }

    pub fn stop(&self) {
        EventEncoder::new("fairroulette.stop").emit();
    }

    pub fn winner(&self, number: i64) {
        let mut encoder = EventEncoder::new("fairroulette.winner");
        encoder.int64(number);
        encoder.emit();
    }
}
```

</TabItem>
<TabItem value="ts">

```ts
import * as wasmlib from "wasmlib";

export class FairRouletteEvents {
    bet(address: wasmlib.ScAddress, amount: i64, number: i64): void {
        new wasmlib.EventEncoder("fairroulette.bet").
        address(address).
        int64(amount).
        int64(number).
        emit();
    }

    payout(address: wasmlib.ScAddress, amount: i64): void {
        new wasmlib.EventEncoder("fairroulette.payout").
        address(address).
        int64(amount).
        emit();
    }

    round(number: i64): void {
        new wasmlib.EventEncoder("fairroulette.round").
        int64(number).
        emit();
    }

    start(): void {
        new wasmlib.EventEncoder("fairroulette.start").
        emit();
    }

    stop(): void {
        new wasmlib.EventEncoder("fairroulette.stop").
        emit();
    }

    winner(number: i64): void {
        new wasmlib.EventEncoder("fairroulette.winner").
        int64(number).
        emit();
    }
}
```

</TabItem>
</Tabs>

Notice how the generated functions use the WasmLib EventEncoder to encode the
parameters into a single string before emitting it. Here is the way in which
`fairroulette` emits the `bet` event in its smart contract code:


<Tabs defaultValue="go"
      groupId="language"
      values={[
          {label: 'Go', value: 'go'},
          {label: 'Rust', value: 'rust'},
          {label: 'TypeScript', value: 'ts'},
      ]}>

<TabItem value="go">

```go
    f.Events.Bet(bet.Better.Address(), bet.Amount, bet.Number)
```

</TabItem>
<TabItem value="rust">

```rust
    f.events.bet(&bet.better.address(), bet.amount, bet.number);
```

</TabItem>
<TabItem value="ts">

```ts
    f.events.bet(bet.better.address(), bet.amount, bet.number);
```

</TabItem>
</Tabs>

The smart contract client code can listen in to the event stream and respond to the
events it deems noteworthy. The schema tool will shortly also be generating the client
side code that properly parses these events and passes a type-safe structure to the
client code.

In the next section we will explore how the schema tool helps to simplify
[function definitions](funcs.mdx).
